#include "bcdidothread.h"
#include "rtdb.h"
#include  <math.h>

float g_runTickCount = 0;
#define PINTT_COUNT 300
int BcDiDoThread::getBCDIValue(CBattBank *pBank, int diIndex)
{
	int ret = 0;
	if(0 == diIndex)
		ret = pBank->usDI1;
	else if(1 == diIndex)
		ret = pBank->usDI2;
	else if(2 == diIndex)
		ret = pBank->usDI3;
	else if(3 == diIndex)
		ret = pBank->usDI4;
	else if(4 == diIndex)
		ret = pBank->usDI5;
	else if(5 == diIndex)
		ret = pBank->usDI6;
	else if(6 == diIndex)
		ret = pBank->aBankTemp[0];
	else if(7 == diIndex)
		ret = pBank->aBankTemp[1]; // 门禁
	else
		ret = 0;
	
	return ret;
}

char getAlarmState(char state, char alarmValue)
{
	char aAlarm = 0;
	
	if(alarmValue > 0)
	{
		if(state > 0)
		{
			aAlarm = 1;
		}
	}
	else
	{
		if(0 == state)
		{
			aAlarm = 1;
		}
	}
	
	return aAlarm;
}

// 有汇流开关时，先等汇流开关断开再脱扣BC上的断路器, 最多等9秒 // added 2024-11-20
void BcDiDoThread::waitConfSwitchBreaked()
{
   if(KgGlobalData::ms_hlkgStrategy.diCfgList.size() > 0 && KgGlobalData::ms_pStack->aConfSwitchState > 0)
   {
	   for(int k = 0; k < 90; ++k)
	   {
		   this->msleep(100);
		   //if(2 == KgGlobalData::ms_pStack->usConfSwitchState)
		   if(0 == KgGlobalData::ms_pStack->aConfSwitchState)// 汇流开关已经断开
		   {
		        for(int m = 0; m < 3; ++m)
		       	{
		       		printf("*******************ConfSwitch has breaked.\n");
		       	}
			   break;
		   }
	   }
   }
}

void BcDiDoThread::dealwithBCDIState(CBattStack *pStack)// added 2024-8-28
{
    //for(int k = 0;  k < 3; ++k)
	//    printf("********************** ms_bcDiList.size() %d\n", KgGlobalData::ms_bcDiList.size());
	if(m_bcDoLogCount < 3000)
	{
		m_bcDoLogCount += 1;
		/*for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
		{
			CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
			printf("888888 BC%d DIState:%d-%d-%d-%d-%d-%d-%d-%d, DOState:%d-%d-%d-%d-%d-%d-%d-%d\n", k+1,
			  pBank->usDI1,pBank->usDI2,pBank->usDI3,pBank->usDI4,pBank->usDI5,pBank->usDI6,getBCDIValue(pBank, 6), getBCDIValue(pBank, 7),
			  pBank->usWetState,pBank->usDry1State,pBank->usDry2State,pBank->usDry3State,
			  pBank->usDry4State,pBank->usDry5State,pBank->usDry6State,pBank->usDry7State);
		}*/
	}
	
	if(0 == (m_runCount%20))// 5秒输出一次
	{
		for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
		{
			if(0 == (KgGlobalData::ms_bcDiCount + KgGlobalData::ms_bcDoCount))
			{
				continue;
			}

			CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
			//if(k < 3)
			//{
			    QString strLog = QString("Read BC%1 DIState:%2-%3-%4-%5-%6-%7-%8-%9, DOState:%10-%11-%12-%13-%14-%15-%16-%17,BankState:%18-%19").arg(k+1)
				        .arg(pBank->usDI1).arg(pBank->usDI2).arg(pBank->usDI3).arg(pBank->usDI4)
				        .arg(pBank->usDI5).arg(pBank->usDI6).arg(getBCDIValue(pBank, 6)).arg(getBCDIValue(pBank, 7))
				        .arg(pBank->usWetState).arg(pBank->usDry1State).arg(pBank->usDry2State).arg(pBank->usDry3State)
				        .arg(pBank->usDry4State).arg(pBank->usDry5State).arg(pBank->usDry6State).arg(pBank->usDry7State)
				        .arg(pBank->usBankState).arg(pBank->usBankChgDchgState);
				writeKgBcLogfile(strLog, true);
			//}
			/*else
			{
				if(m_bcDoLogCount < 100)
				{
				    printf("Read BC%d DIState:%d-%d-%d-%d-%d-%d-%d-%d, DOState:%d-%d-%d-%d-%d-%d-%d-%d, BankState:%04X-%d\n", k+1,
				    pBank->usDI1,pBank->usDI2,pBank->usDI3,pBank->usDI4,pBank->usDI5,pBank->usDI6,getBCDIValue(pBank, 6), getBCDIValue(pBank, 7),
				    pBank->usWetState,pBank->usDry1State,pBank->usDry2State,pBank->usDry3State,
				    pBank->usDry4State,pBank->usDry5State,pBank->usDry6State,pBank->usDry7State,
				    pBank->usBankState,pBank->usBankChgDchgState);
				}
			}*/
		}
	}

	if(0 == KgGlobalData::ms_bcDiList.size())
	{	
		return;
	}

	for(int i = 0; i < KgGlobalData::ms_bcDiList.size(); ++i)
	{
		DI_STU diStg = KgGlobalData::ms_bcDiList[i];
		int iStrategy = diStg.iStrategy;
		QString str = QString(" (Stg:%1,Alarm:%2)").arg(iStrategy).arg((int)diStg.alarmValue);

		if (1 == iStrategy)		// 1:汇流开关反馈
		{	
			writeKgLogfile(QString("BC DI%1 is hzkg state node%2.").arg(diStg.diIndex+1).arg(str));	
		}
		else if (2 == iStrategy)// 2:隔离开关反馈
		{
			writeKgLogfile(QString("BC DI%1 is isolSwitch state node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (3 == iStrategy)// 3:主断路器反馈
		{
			writeKgLogfile(QString("BC DI%1 is mainSwitch state node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (8 == iStrategy)// 8:防雷采集干结点 
		{
			writeKgLogfile(QString("BC DI%1 is thunder state node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (108 == iStrategy)// 18:#2防雷采集干结点  ***************
		{
			writeKgLogfile(QString("BC DI%1 is #2thunder state node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (9 == iStrategy)// 9:消防采集干结点 
		{
			writeKgLogfile(QString("BC DI%1 is XF alarm state node%2.").arg(diStg.diIndex+1).arg(str));
			char aFireAlarm = 0;
			char usDIState = 0;
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				int diValue = getBCDIValue(pBank, diStg.diIndex);
				char aTmpAlarm = 0;
				if(0 == k)
				{
					usDIState = diValue;
				}

				if(getAlarmState(diValue, diStg.alarmValue) > 0)
				{
					aFireAlarm = 1;
					aTmpAlarm = 1;
				}
				
				if(99 != m_bcDiOldState[k][5])
				{
					if(diValue != m_bcDiOldState[k][5])
					{
						if(isChLang())
						{
							if(aTmpAlarm > 0)
								saveBcLogToBaDb(kgConvert("%1#簇发生消防报警.").arg(k+1));
							else
								saveBcLogToBaDb(kgConvert("%1#簇消防报警结束.").arg(k+1));
						}
						else
						{
							if(aTmpAlarm > 0)
								saveBcLogToBaDb(kgConvert("%1# cluster has fire alarm.").arg(k+1));
							else
								saveBcLogToBaDb(kgConvert("%1# cluster fire alarm over.").arg(k+1));
						}	
					}
				}

			    if(99 == m_bcDiOldState[k][5])
			    {
					if(aTmpAlarm > 0)
					{
						if(isChLang())
						   writeKgBcLogfile(kgConvert("[%1#簇发生消防报警].").arg(k+1),true);
						else
						   writeKgBcLogfile(kgConvert("%1# cluster has fire alarm.").arg(k+1),true);
					}
			    }
				m_bcDiOldState[k][5] = diValue;
			}

			if(m_bcDoLogCount < 3000)
			{//2026
				//printf("8888888888888888888888888 aFireWarn:%d, DIState:%d (alarmValue:%d)\n", 
				//	(int)pStack->aFireWarn, (int)usDIState, (int)diStg.alarmValue);
			}
			pStack->aFireWarn = aFireAlarm;// added 2024-9-5
		}
		else if (10 == iStrategy)// 10:水浸采集干结点 
		{
			writeKgLogfile(QString("BC DI%1 is Water come state node%2.").arg(diStg.diIndex+1).arg(str));
			char aWaterAlarm = 0;
			char usDIState = 0;
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				int diValue = getBCDIValue(pBank, diStg.diIndex);
				char aTmpAlarm = 0;
				if(0 == k)
				{
					usDIState = diValue;
				}

				if(getAlarmState(diValue, diStg.alarmValue) > 0)
				{
					aWaterAlarm = 1;
					aTmpAlarm = 1;
				}

				if(99 != m_bcDiOldState[k][1])
				{
					if(diValue != m_bcDiOldState[k][1])
					{
						if(isChLang())
						{
							if(aTmpAlarm > 0)
					   			saveBcLogToBaDb(kgConvert("%1#簇发生水浸报警.").arg(k+1));
							else
					  	    	saveBcLogToBaDb(kgConvert("%1#簇水浸报警结束.").arg(k+1));
						}
						else
						{
							if(aTmpAlarm > 0)
								saveBcLogToBaDb(kgConvert("%1# cluster has water alarm.").arg(k+1));
							else
								saveBcLogToBaDb(kgConvert("%1# cluster water alarm over.").arg(k+1));
						}
					}
				}
				
				if(99 == m_bcDiOldState[k][1])
			    {
			    	if(isChLang())
			    	{
						if(aTmpAlarm > 0)
							writeKgBcLogfile(kgConvert("[%1#簇发生水浸报警].").arg(k+1),true);
			    	}
					else
					{
						if(aTmpAlarm > 0)
							writeKgBcLogfile(kgConvert("[%1# cluster has water alarm].").arg(k+1), true);
					}
			    }
				m_bcDiOldState[k][1] = diValue;
#ifdef WTGZ_PRJ
			   pBank = KgGlobalData::ms_pRTDB->getBank(14);
			   if(pBank &&	k < 7)
				{
					pBank->usBankTemp[7+k] = aTmpAlarm;
				}
#endif

			}
			
			if(m_bcDoLogCount < 300)
			{// 2026
				//printf("8888888888888888888888888 aWaterAlarm:%d, diValue:%d (alarmValue:%d)\n", 
				//	(int)pStack->aWaterAlarm, (int)usDIState, (int)diStg.alarmValue);
			}
			//pStack->aWaterAlarm = aWaterAlarm; // 2026
		}
		else if (110 == iStrategy)// 100:#2水浸采集干结点 ***************
		{
			writeKgLogfile(QString("BC DI%1 is #2Water come state node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (11 == iStrategy)// 11:急停信号采集干结点 
		{
			writeKgLogfile(QString("BC DI%1 is emergency stop node%2.").arg(diStg.diIndex+1).arg(str));
			char aEmergStop = 0;
			char usDIState = 0;
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				int diValue = getBCDIValue(pBank, diStg.diIndex);
				char aTmpAlarm = 0;
				if(0 == k)
				{
					usDIState = diValue;
				}

				if(getAlarmState(diValue, diStg.alarmValue) > 0)
				{
					aEmergStop = 1;
					aTmpAlarm = 1;
				}

				if(99 != m_bcDiOldState[k][2])
				{
					if(diValue != m_bcDiOldState[k][2])
					{
						if(isChLang())
						{
							if(aTmpAlarm > 0)
								saveBcLogToBaDb(kgConvert("%1#簇发生急停.").arg(k+1));
							else
								saveBcLogToBaDb(kgConvert("%1#簇急停结束.").arg(k+1));
						}
						else
						{
							if(aTmpAlarm > 0)
								saveBcLogToBaDb(kgConvert("%1# cluster has emergStop.").arg(k+1));
							else
								saveBcLogToBaDb(kgConvert("%1# cluster emergStop over.").arg(k+1));
						}
					}
				}

			   if(99 == m_bcDiOldState[k][2])
			   {
			   	    if(isChLang())
			   	    {
						if(aTmpAlarm > 0)
							writeKgBcLogfile(kgConvert("[%1#簇发生急停].").arg(k+1),true);
			   	    }
					else
					{
						if(aTmpAlarm > 0)
							writeKgBcLogfile(kgConvert("[%1# cluster has emergStop].").arg(k+1),true);					
					}
			   }
				
			   m_bcDiOldState[k][2] = diValue;
#ifdef WTGZ_PRJ
			    pBank = KgGlobalData::ms_pRTDB->getBank(14);
			   if(pBank &&  k < 7)
			   	{
			   		pBank->usBankTemp[k] = aTmpAlarm;
			   	}
#endif
			}

			if(m_bcDoLogCount < 300)
			{
				//printf("8888888888888888888888888 aEmerStop:%d, DIState:%d (alarmValue:%d)\n", 
				//	(int)pStack->aEmerStop, (int)usDIState, (int)diStg.alarmValue);
			}
			//pStack->aEmerStop = aEmergStop;// added 2024-9-5 // 2026
		}
		else if (111 == iStrategy)// 111:#2急停信号采集干结点 ***************
		{
			writeKgLogfile(QString("BC DI%1 is #2emergency stop node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (12 == iStrategy)// 12:可燃气体采集干结点 
		{
			writeKgLogfile(QString("BC DI%1 is combustible gas node%2.").arg(diStg.diIndex+1).arg(str));
		}
		// added 2022-3-27
		else if (13 == iStrategy)// 13:熔断器采集反馈干结点 
		{
			writeKgLogfile(QString("BC DI%1 is fuse node%2.").arg(diStg.diIndex+1).arg(str));
		}
		// added 2022-4-6
		else if (14 == iStrategy)// 14:消防释放信号
		{

			writeKgLogfile(QString("BC DI%1 is XF motion node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (20 == iStrategy)	// 20:充电接触器驱动信号
		{
			writeKgLogfile(QString("BC DI%1 is charge drive FK node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (21 == iStrategy)	// 21:放电接触器驱动信号
		{
			writeKgLogfile(QString("BC DI%1 is discharge drive FK node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (22 == iStrategy)	// 22:消防预警信号
		{
			writeKgLogfile(QString("BC DI%1 is XF Warm node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (23 == iStrategy)	// 23:UPS告警信号
		{
			writeKgLogfile(QString("BC DI%1 is Ups node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (24 == iStrategy)	// 24:门禁告警信号
		{
			writeKgLogfile(QString("BC DI%1 is Door node%2.").arg(diStg.diIndex+1).arg(str));
			char aDoorAlarm = 0;
			char usDIState = 0;
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				int diValue = getBCDIValue(pBank, diStg.diIndex);
				char aTmpAlarm = 0;
				if(0 == k)
				{
					usDIState = diValue;
				}

				if(getAlarmState(diValue, diStg.alarmValue) > 0)
				{
					aDoorAlarm = 1;
					aTmpAlarm = 1;
				}

				if(99 != m_bcDiOldState[k][3])
				{
					if(diValue != m_bcDiOldState[k][3])
					{
						if(isChLang())
						{
							if(aTmpAlarm > 0)
							   saveBcLogToBaDb(kgConvert("%1#簇发生门禁告警.").arg(k+1));
							else
							   saveBcLogToBaDb(kgConvert("%1#簇门禁告警结束.").arg(k+1));
						}
						else
						{
							if(aTmpAlarm > 0)
								saveBcLogToBaDb(kgConvert("%1# cluster has door alarm.").arg(k+1));
							else
								saveBcLogToBaDb(kgConvert("%1# cluster door alarm over.").arg(k+1));
						}
					}
				}

				if(99 == m_bcDiOldState[k][3])
			    {
			       if(isChLang())
			       	{
						if(aTmpAlarm > 0)
							writeKgBcLogfile(kgConvert("[%1#簇发生门禁告警].").arg(k+1),true);
			       	}
				    else
					{
						if(aTmpAlarm > 0)
							writeKgBcLogfile(kgConvert("[%1# cluster has door alarm].").arg(k+1),true);
					}
				  }
				m_bcDiOldState[k][3] = diValue;
#ifdef WTGZ_PRJ
			   pBank = KgGlobalData::ms_pRTDB->getBank(14);
			   if(pBank &&	k < 7)
				{
					pBank->usBankTemp[14+k] = aTmpAlarm;
				}
#endif
			}
			
			if(m_bcDoLogCount < 300)
			{// 2026
				//printf("8888888888888888888888888 aAcceCtrlState:%d, DIState:%d (alarmValue:%d)\n", 
				//	  (int)pStack->aAcceCtrlState, (int)usDIState, (int)diStg.alarmValue);
			}
			//pStack->aAcceCtrlState = aDoorAlarm;// 2026

		}
		else if (34 == iStrategy)	// 34:门禁告警信号2   added 2023-5-4
		{
			writeKgLogfile(QString("BC DI%1 is Door Sec node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (25 == iStrategy)	// 25:消防喷洒信号 added 2022-12-10
		{	
			writeKgLogfile(QString("BC DI%1 is XF Spray state node%2.").arg(diStg.diIndex+1).arg(str));
			char aFireSpary = 0;
			char usDIState = 0;
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				int diValue = getBCDIValue(pBank, diStg.diIndex);
				char aTmpAlarm = 0;
				if(0 == k)
				{
					usDIState = diValue;
				}

				if(getAlarmState(diValue, diStg.alarmValue) > 0)
				{
					aFireSpary = 1;
					aTmpAlarm = 1;
				}
				
				if(99 != m_bcDiOldState[k][6])
				{
					if(diValue != m_bcDiOldState[k][6])
					{
						if(isChLang())
						{
							if(aTmpAlarm > 0)
								saveBcLogToBaDb(kgConvert("%1#簇发生消防启动.").arg(k+1));
							else
								saveBcLogToBaDb(kgConvert("%1#簇消防启动结束.").arg(k+1));
						}
						else
						{
							if(aTmpAlarm > 0)
								saveBcLogToBaDb(kgConvert("%1# cluster has fire action.").arg(k+1));
							else
								saveBcLogToBaDb(kgConvert("%1# cluster fire action over.").arg(k+1));
						}
					}
				}

				if(99 == m_bcDiOldState[k][6])
			    {
			        if(isChLang())
			        {
						if(aTmpAlarm > 0)
							writeKgBcLogfile(kgConvert("[%1#簇发生消防启动].").arg(k+1),true);
			        }
					else
					{
						if(aTmpAlarm > 0)
							writeKgBcLogfile(kgConvert("[%1# cluster has fire action].").arg(k+1),true);
					}
			    }
				m_bcDiOldState[k][6] = diValue;
			}

			if(m_bcDoLogCount < 300)
			{
			// 2026
				//printf("8888888888888888888888888 aFireAction:%d, DIState:%d (alarmValue:%d)\n", 
				//	(int)pStack->aFireAction, (int)usDIState, (int)diStg.alarmValue);
			}
			pStack->aFireAction = aFireSpary;// added 2024-9-
		}
		else if (26 == iStrategy)	// 26:消防故障 added 2022-12-21
		{
			writeKgLogfile(QString("BC DI%1 is XF Fault state node%2.").arg(diStg.diIndex+1).arg(str));
			char aFireFault = 0;
			char usDIState = 0;
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				int diValue = getBCDIValue(pBank, diStg.diIndex);
				char aTmpAlarm = 0;
				if(0 == k)
				{
					usDIState = diValue;
				}

				if(getAlarmState(diValue, diStg.alarmValue) > 0)
				{
					aFireFault = 1;
					aTmpAlarm = 1;
				}
				
				if(99 != m_bcDiOldState[k][7])
				{
					if(diValue != m_bcDiOldState[k][7])
					{
						if(isChLang())
						{
							if(aTmpAlarm > 0)
								saveBcLogToBaDb(kgConvert("%1#簇发生消防故障.").arg(k+1));
							else
								saveBcLogToBaDb(kgConvert("%1#簇消防故障结束.").arg(k+1));
						}
						else
						{
							if(aTmpAlarm > 0)
								saveBcLogToBaDb(kgConvert("%1# cluster has fire fault.").arg(k+1));
							else
								saveBcLogToBaDb(kgConvert("%1# cluster fire fault over.").arg(k+1));
						}
					}
				}

				if(99 == m_bcDiOldState[k][7])
			    {
			    	if(isChLang())
			    	{
						if(aTmpAlarm > 0)
							writeKgBcLogfile(kgConvert("[%1#簇发生消防故障].").arg(k+1),true);
			    	}
					else
					{
						if(aTmpAlarm > 0)
							writeKgBcLogfile(kgConvert("%1# cluster has fire fault.").arg(k+1),true);
					}
				}
				m_bcDiOldState[k][7] = diValue;
			}

			if(m_bcDoLogCount < 300)
			{// 2026
				//printf("8888888888888888888888888 aFireFault:%d, DIState:%d (alarmValue:%d)\n", 
				//	(int)pStack->aFireFault, (int)usDIState, (int)diStg.alarmValue);
			}
			//pStack->aFireFault = aFireFault;// added 2024-9- // 2026
		}
		else if (27 == iStrategy)	// 27:消防手动/自动 added 2023-11-9
		{
			writeKgLogfile(QString("BC DI%1 is XF manu/auto mode node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (30 == iStrategy)	// 30:市电断电 added 2023-11-9
		{
			writeKgLogfile(QString("BC DI%1 is Elec power off node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (31 == iStrategy)	// 31:BMS就地 added 2023-12-25
		{
			writeKgLogfile(QString("BC DI%1 is Bms local node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (32 == iStrategy)	// 32:BMS远方
		{
			writeKgLogfile(QString("BC DI%1 is Bms remote node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (41 == iStrategy)	// 41:空调机组故障 added 2024-2-3
		{
			writeKgLogfile(QString("BC DI%1 is AC fault node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (42 == iStrategy)	// 42:液冷机组故障 added 2024-2-3
		{
			writeKgLogfile(QString("BC DI%1 is LQ fault node%2.").arg(diStg.diIndex+1).arg(str));
		}
		else if (iStrategy >= 51 && iStrategy <= 58)	// 51:备用信号 added 2023-8-19
		{
			int retNo = iStrategy - 51;
			//initResAlarm(i, retNo, resStg, strDIName, strDIOverName);
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				int diValue = getBCDIValue(pBank, diStg.diIndex);
				char aTmpAlarm = 0;
				if(getAlarmState(diValue, diStg.alarmValue) > 0)
				{
					aTmpAlarm = 1;
				}
				
				if(99 != m_bcResDiOldState[k][retNo])
				{
					if(diValue != m_bcResDiOldState[k][retNo])
					{
						if(isChLang())
						{
							if(aTmpAlarm > 0)
							   saveBcLogToBaDb(kgConvert("%1#簇%2.").arg(k+1).arg(diStg.diName));
							else
							   saveBcLogToBaDb(kgConvert("%1#簇%2.").arg(k+1).arg(diStg.diOverName));
						}
						else
						{
							if(aTmpAlarm > 0)
							   saveBcLogToBaDb(kgConvert("%1# cluster %2.").arg(k+1).arg(diStg.diName));
							else
							   saveBcLogToBaDb(kgConvert("%1# cluster %2.").arg(k+1).arg(diStg.diOverName));
						}
					}
				}

				if(99 == m_bcResDiOldState[k][retNo])
			    {
			    	if(isChLang())
			    	{
						if(aTmpAlarm > 0)
							writeKgBcLogfile(kgConvert("[%1#簇%2].").arg(k+1).arg(diStg.diName),true);
			    	}
					else
					{
						if(aTmpAlarm > 0)
							writeKgBcLogfile(kgConvert("%1# cluster %2.").arg(k+1).arg(diStg.diName),true);
					}
			    }
				m_bcResDiOldState[k][retNo] = diValue;
			}
		}
		else
		{
			// bUsed = false;
		}
	}
}

 // added 2024-11-15
int  getBCDOState(CBattBank *pBank, DOStrategy doStg)
{
	int state = 0;
    if(0 == doStg.doIndex)
	{
		state = pBank->usWetState;
	}
	else if(1 == doStg.doIndex)
	{
		state = pBank->usDry1State;
	}
	else if(2 == doStg.doIndex)
	{
		state = pBank->usDry2State;
	}
    else if(3 == doStg.doIndex)
	{
	    state = pBank->usDry3State;
	}
	else if(4 == doStg.doIndex)
	{
	    state = pBank->usDry4State;
	}
	else if(5 == doStg.doIndex)
	{
	   state = pBank->usDry5State;
	}
	else if(6 == doStg.doIndex)
	{
	    state = pBank->usDry6State;
	}
	else if(7 == doStg.doIndex)
	{
	    state = pBank->usDry7State;
	}
	else
		;
	return state;
}

void ctrlBcCloseDO(CBattBank *pBank, DOStrategy doStg)
{
    if(3 == doStg.doIndex)
	{
	    if(0 == pBank->usDry3State)
	    {
			pBank->usDry3Ctrl = 1;    // 干接点5控制  
			pBank->iDry3CtrlNum = 3;  // 干接点5控制次数
	    }
	}
	else if(4 == doStg.doIndex)
	{
	    if(0 == pBank->usDry4State)
	    {
			pBank->usDry4Ctrl = 1;    // 干接点5控制  
			pBank->iDry4CtrlNum = 3;  // 干接点5控制次数
	    }
	}
	else if(5 == doStg.doIndex)
	{
	    if(0 == pBank->usDry5State)
	    {
			pBank->usDry5Ctrl = 1;    // 干接点5控制  
			pBank->iDry5CtrlNum = 3;  // 干接点5控制次数
	    }
	}
	else if(6 == doStg.doIndex)
	{
	    if(0 == pBank->usDry6State)
	    {
			pBank->usDry6Ctrl = 1;    // 干接点5控制  
			pBank->iDry6CtrlNum = 3;  // 干接点5控制次数
	    }
	}
	else if(7 == doStg.doIndex)
	{
	    if(0 == pBank->usDry7State)
	    {
			pBank->usDry7Ctrl = 1;    // 干接点5控制  
			pBank->iDry7CtrlNum = 3;  // 干接点5控制次数
	    }
	}
	else
		;
}

void ctrlBcOpenDO(CBattBank *pBank, DOStrategy doStg)
{
	if(3 == doStg.doIndex)
	{
	    if(1 == pBank->usDry3State)
	    {
			pBank->usDry3Ctrl = 0;    // 干接点5控制  
			pBank->iDry3CtrlNum = 3;  // 干接点5控制次数
	    }
	}
	else if(4 == doStg.doIndex)
	{
	    if(1 == pBank->usDry4State)
	    {
			pBank->usDry4Ctrl = 0;    // 干接点5控制  
			pBank->iDry4CtrlNum = 3;  // 干接点5控制次数
	    }
	}
	else if(5 == doStg.doIndex)
	{
	    if(1 == pBank->usDry5State)
	    {
			pBank->usDry5Ctrl = 0;    // 干接点5控制  
			pBank->iDry5CtrlNum = 3;  // 干接点5控制次数
	    }
	}
	else if(6 == doStg.doIndex)
	{
	    if(1 == pBank->usDry6State)
	    {
			pBank->usDry6Ctrl = 0;    // 干接点5控制  
			pBank->iDry6CtrlNum = 3;  // 干接点5控制次数
	    }
	}
	else if(7 == doStg.doIndex)
	{
	    if(1 == pBank->usDry7State)
	    {
			pBank->usDry7Ctrl = 0;    // 干接点5控制  
			pBank->iDry7CtrlNum = 3;  // 干接点5控制次数
	    }
	}
	else
		;
}

int bankCount[20]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // 输出日志用
int bankState[20]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // 上一次簇状态     102策略
int bankEmg[20]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};   // 上一次簇急停状态 102策略
int bankFireAction[20]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 
int bankFireFault[20]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 

int bankCountSec[20]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};// 输出日志用
int bankStateSec[20]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};// 上一次簇状态     103策略
int bankEmgSec[20]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};  // 上一次簇急停状态 103策略
int bankFireActionSec[20]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 

int bingLianMode = 1; // 1-并联模式 0-各簇独立 // added 2024-10-26
int fanStartLogCount = 0;
int fanStopLogCount = 0;
int fanState[20]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 

void BcDiDoThread::dealwithBCDOState()// added 2024-9-29
{
	if(0 == KgGlobalData::ms_bcDoList.size())
	{	
		return;
	}

	CBattStack *pStack = KgGlobalData::ms_pStack;
	
	for(int i = 0; i <  KgGlobalData::ms_bcDoList.size(); ++i) // read DO Strategy
    {
    	DOStrategy doStg = KgGlobalData::ms_bcDoList[i];
		if(1 == doStg.iStrategy) // 故障灯
		{
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				//if(m_usAllProt > 0)
				if(0xAAAA == pBank->usBankState)
				{
				   ctrlBcCloseDO(pBank, doStg);
				   if(m_printCount < PINTT_COUNT)
				      printf("****HasError, CloseBc%d DO%d (1-ErrorLamp) light\n", k+1, doStg.doIndex+1);
				}
				else
				{
				   ctrlBcOpenDO(pBank, doStg);
				   if(m_printCount < PINTT_COUNT)
				       printf("****NoError, OpenBc%d DO%d (1-ErrorLamp)\n", k+1, doStg.doIndex+1);
				}
			}
		}
		else if(6 == doStg.iStrategy) // 运行灯
		{
		    for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				//if(0 == m_usAllProt)
				if(0xAAAA != pBank->usBankState && 0x5555 != pBank->usBankState)
				{
				    ctrlBcCloseDO(pBank, doStg);
					if(m_printCount < PINTT_COUNT)
				       printf("****NoError, CloseBc%d DO%d (6-RunLamp) light\n", k+1, doStg.doIndex+1);
				}
				else
				{
				    ctrlBcOpenDO(pBank, doStg);
					if(m_printCount < PINTT_COUNT)
				       printf("****HasError, OpenBc%d DO%d (6-RunLamp)\n", k+1, doStg.doIndex+1);
				}
			}
		}
		else if(124 == doStg.iStrategy) // 风扇
		{
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				/*CBankAlarm *pBankAlarm = KgGlobalData::ms_pRTDB->getBankAlarm(k);2026

				// modified 2024-10-15
			    //if(pBank->fSglMaxTemp > pBankAlarm->param.fChargeSglTempUpLimitWarn ||
			   	//  pBank->fSglMaxTemp > pBankAlarm->param.fDchargeSglTempUpLimitWarn)
			   	
				//if(pBank->aChgTempUpLimitWarn + pBank->aChgTempUpLimitAlarm + pBank->aChgTempUpLimitProt + 
				//   pBank->aDchgTempUpLimitWarn + pBank->aDchgTempUpLimitAlarm + pBank->aDchgTempUpLimitProt > 0)
				
				bool bRetVal = false;
				float fSglMaxTemp = pBank->fSglMaxTemp;
				if (fSglMaxTemp > pBankAlarm->param.fChargeSglTempUpLimitWarn - 5 || 
					fSglMaxTemp > pBankAlarm->param.fChargeSglTempUpLimitAlarm - 5 || 
					fSglMaxTemp > pBankAlarm->param.fChargeSglTempUpLimitProt - 5 || 
					fSglMaxTemp > pBankAlarm->param.fDchargeSglTempUpLimitWarn - 5 || 
					fSglMaxTemp > pBankAlarm->param.fDchargeSglTempUpLimitAlarm - 5 || 
					fSglMaxTemp > pBankAlarm->param.fDchargeSglTempUpLimitProt - 5 )
				{
					printf("Bank%d aChgTempUpLimitAlarm:%d, aChgTempUpLimitProt:%d, aDchgTempUpLimitAlarm:%d, aDchgTempUpLimitProt:%d\n",
						k+1, (int)pBank->aChgTempUpLimitAlarm, (int)pBank->aChgTempUpLimitProt, (int)pBank->aDchgTempUpLimitAlarm, (int)pBank->aDchgTempUpLimitProt);

					printf("Bank%d fSglMaxTemp:%.1f, fChargeSglTempUpLimitWarn:%.1f, fDchargeSglTempUpLimitWarn:%.1f\n",
						k+1, pBank->fSglMaxTemp, pBankAlarm->param.fChargeSglTempUpLimitWarn, pBankAlarm->param.fDchargeSglTempUpLimitWarn);

					ctrlBcCloseDO(pBank, doStg);
					fanState[k] = 1;

					if(0 == fanStartLogCount)
					{
						fanStartLogCount += 1;
						if(isChLang())
						   saveBcLogToBaDb(kgConvert("%1#簇温度高, 启动风机(DO%1).").arg(k+1).arg(doStg.doIndex+1));
						else
						   saveBcLogToBaDb(kgConvert("%1# cluster temperatue high, open fan(DO%1).").arg(k+1).arg(doStg.doIndex+1));
					}
					if(m_printCount < PINTT_COUNT)
				       printf("****Temp higher, CloseBc%d DO%d (24-Fan) light\n", k+1, doStg.doIndex+1);
				}
				else
				{
				    ctrlBcOpenDO(pBank, doStg);
					if(1 == fanState[k] && 0 == fanStopLogCount)
					{
						fanStopLogCount += 1;
						if(isChLang())
						   saveBcLogToBaDb(kgConvert("%1#簇温度正常, 关闭风机(DO%1).").arg(k+1).arg(doStg.doIndex+1));
						else
						   saveBcLogToBaDb(kgConvert("%1# cluster temperatue normal, close fan(DO%1).").arg(k+1).arg(doStg.doIndex+1));
					}
					fanState[k] = 0;
					if(m_printCount < PINTT_COUNT)
				       printf("****Temp not higher, OpenBc%d DO%d (24-Fan)\n", k+1, doStg.doIndex+1);
				}
				
				if(m_printCount < PINTT_COUNT)
					 printf("****Bc%d DI1-DI6 state:%d-%d-%d-%d-%d-%d\n", 
					 k+1, pBank->usDI1, pBank->usDI2, pBank->usDI3, pBank->usDI4, pBank->usDI5,
					 pBank->usDI6);
				
				if(m_printCount < PINTT_COUNT)
					 printf("****Bc%d DO1-DO8 state:%d(Wet)-%d-%d-%d(ErrLamp)-%d(RunLamp)-%d(Fan)-%d(DLQ)-%d\n", 
					 k+1, pBank->usWetState, pBank->usDry1State, pBank->usDry2State, pBank->usDry3State,
					 pBank->usDry4State,pBank->usDry5State,pBank->usDry6State,pBank->usDry7State);
					 */
			}
		}
		/*
		for(k = 0; k < KgGlobalData::ms_fanDriveList.size(); ++k)
			{
				DOStrategy stg = KgGlobalData::ms_fanDriveList[k];
				float fStackCur = fabs(KgGlobalData::ms_pStack->fStackCur);

				
				// modified 2023-12-17
				if (m_fireAlarm || m_fireSprayAlarm || usEmergStopAlarm || fStackCur < KgGlobalData::ms_minChgDchgCur) 
				{
					if(0 == m_oldCtrlFanState)
					{
						setDoState(newIOCtrl, stg.doIndex, 0); // 没有充放电，关闭风扇
					}
					else // 有驱动过风扇, 延时关闭
					{
						if(0 == m_closeFanReqCount)
						{
							m_closeReqStartTime = QDateTime::currentDateTime();
							m_closeFanReqCount += 1;
						}
						else
						{
							QDateTime nowTime = QDateTime::currentDateTime();
							int elapseSec  = m_closeReqStartTime.secsTo(nowTime);
							if(elapseSec >= KgGlobalData::ms_closeFanDelayTime)
							{
								m_oldCtrlFanState = 0; // 驱动风扇标记清0
							}
						}
					}
				}
				else
				{
					m_oldCtrlFanState = 1; // 驱动风扇标记
					m_closeFanReqCount = 0;
					setDoState(newIOCtrl, stg.doIndex, 1); // 有充放电，打开风扇
				}
			}
		*/
		else if(24 == doStg.iStrategy) // 根据簇电流控制风扇 // added 2024-11-30
		{
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				 // CBankAlarm *pBankAlarm = KgGlobalData::ms_pRTDB->getBankAlarm(k);
				if(0xAAAA == pBank->usBankState || fabs(pBank->fBankCur) < 2)
				{
				    if(0 == m_oldCtrlFanState[k])
					{
						 ctrlBcOpenDO(pBank, doStg);// 没有充放电，关闭风扇
						 QString strLog = QString("Bank%1 stop fan(DO%2),bankState:%3,bankCur:%4A.").arg(k+1).arg(doStg.doIndex+1)
						 	.arg(pBank->usBankState).arg(pBank->fBankCur);
					     writeKgBcLogfile(strLog, true);
					}
					else // 有驱动过风扇, 延时关闭
					{
						if(0 == m_closeFanReqCount[k])
						{
							m_closeReqStartTime[k] = QDateTime::currentDateTime();
							m_closeFanReqCount[k] += 1;
						}
						else
						{
							QDateTime nowTime = QDateTime::currentDateTime();
							int elapseSec  = m_closeReqStartTime[k].secsTo(nowTime);
							if(elapseSec >= KgGlobalData::ms_closeFanDelayTime)
							{
								m_oldCtrlFanState[k] = 0; // 驱动风扇标记清0
							}
							else
							{
								QString strLog = QString("Bank%1 keep fan on(DO%2),bankState:%3,bankCur:%4A,keepTime:%5S.").arg(k+1).arg(doStg.doIndex+1)
									.arg(pBank->usBankState).arg(pBank->fBankCur).arg(KgGlobalData::ms_closeFanDelayTime);
					            writeKgBcLogfile(strLog, true);
							}
						}
					}
				}
				else
				{
					ctrlBcCloseDO(pBank, doStg);// 有充放电，打开风扇
					m_oldCtrlFanState[k] = 1; // 驱动风扇标记
					m_closeFanReqCount[k] = 0;

					QString strLog = QString("Bank%1 start fan(DO%2),bankState:%3,bankCur:%4A.").arg(k+1).arg(doStg.doIndex+1)
						.arg(pBank->usBankState).arg(pBank->fBankCur);
					writeKgBcLogfile(strLog, true);
				}
			}
		}
		else if(25 == doStg.iStrategy) // 风扇 
		{
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				// CBankAlarm *pBankAlarm = KgGlobalData::ms_pRTDB->getBankAlarm(k);
				// 2026

				// modified 2024-10-15
			    //if(pBank->fSglMaxTemp > pBankAlarm->param.fChargeSglTempUpLimitWarn ||
			   	//  pBank->fSglMaxTemp > pBankAlarm->param.fDchargeSglTempUpLimitWarn)
			   	
				//if(pBank->aChgTempUpLimitWarn + pBank->aChgTempUpLimitAlarm + pBank->aChgTempUpLimitProt + 
				//   pBank->aDchgTempUpLimitWarn + pBank->aDchgTempUpLimitAlarm + pBank->aDchgTempUpLimitProt > 0)

				bool bRetVal = false;
				float fSglMaxTemp = pBank->fSglMaxTemp;
				if(getBCDOState(pBank, doStg) == 0) // modified 2024-11-15
				{
					/*if (fSglMaxTemp > pBankAlarm->param.fChargeSglTempUpLimitWarn || 
						fSglMaxTemp > pBankAlarm->param.fDchargeSglTempUpLimitWarn)
					{
						printf("Bank%d aChgTempUpLimitAlarm:%d, aChgTempUpLimitProt:%d, aDchgTempUpLimitAlarm:%d, aDchgTempUpLimitProt:%d\n",
							k+1, (int)pBank->aChgTempUpLimitAlarm, (int)pBank->aChgTempUpLimitProt, (int)pBank->aDchgTempUpLimitAlarm, (int)pBank->aDchgTempUpLimitProt);

						printf("Bank%d fSglMaxTemp:%.1f, fChargeSglTempUpLimitWarn:%.1f, fDchargeSglTempUpLimitWarn:%.1f\n",
							k+1, pBank->fSglMaxTemp, pBankAlarm->param.fChargeSglTempUpLimitWarn, pBankAlarm->param.fDchargeSglTempUpLimitWarn);

						ctrlBcCloseDO(pBank, doStg);//
						fanState[k] = 1;

						if(0 == fanStartLogCount)
						{
							fanStartLogCount += 1;
							if(isChLang())
							   saveBcLogToBaDb(kgConvert("%1#簇温度高, 启动风机(DO%1).").arg(k+1).arg(doStg.doIndex+1));
							else
						       saveBcLogToBaDb(kgConvert("%1# cluster temperatue high, open fan(DO%1).").arg(k+1).arg(doStg.doIndex+1));
						}
						if(m_printCount < PINTT_COUNT)
					       printf("****Temp higher, CloseBc%d DO%d (24-Fan).\n", k+1, doStg.doIndex+1);
					}
					else
					{
					    ctrlBcOpenDO(pBank, doStg);//
						if(1 == fanState[k] && 0 == fanStopLogCount)
						{
							fanStopLogCount += 1;
							if(isChLang())
							    saveBcLogToBaDb(kgConvert("%1#簇温度正常, 关闭风机(DO%1).").arg(k+1).arg(doStg.doIndex+1));
							else
								saveBcLogToBaDb(kgConvert("%1# cluster temperatue normal, close fan(DO%1).").arg(k+1).arg(doStg.doIndex+1));
						}
						fanState[k] = 0;
						if(m_printCount < PINTT_COUNT)
					       printf("****Temp not higher, OpenBc%d DO%d (24-Fan)\n", k+1, doStg.doIndex+1);
					}*/
				}
				else
				{
				    // 已打开, 只要大于回差值, 都打开 2026
					/*if (fSglMaxTemp > (pBankAlarm->param.fChargeSglTempUpLimitWarn - pBankAlarm->param.fChargeSglTempUpLimitWarnHC) || 
						fSglMaxTemp > (pBankAlarm->param.fDchargeSglTempUpLimitWarn - pBankAlarm->param.fDchargeSglTempUpLimitWarnHC))
					{
						printf("Bank%d aChgTempUpLimitAlarm:%d, aChgTempUpLimitProt:%d, aDchgTempUpLimitAlarm:%d, aDchgTempUpLimitProt:%d\n",
							k+1, (int)pBank->aChgTempUpLimitAlarm, (int)pBank->aChgTempUpLimitProt, (int)pBank->aDchgTempUpLimitAlarm, (int)pBank->aDchgTempUpLimitProt);

						printf("Bank%d fSglMaxTemp:%.1f, fChargeSglTempUpLimitWarn:%.1f, fDchargeSglTempUpLimitWarn:%.1f\n",
							k+1, pBank->fSglMaxTemp, pBankAlarm->param.fChargeSglTempUpLimitWarn, pBankAlarm->param.fDchargeSglTempUpLimitWarn);

						ctrlBcCloseDO(pBank, doStg);
						fanState[k] = 1;

						if(0 == fanStartLogCount)
						{
							fanStartLogCount += 1;
							if(isChLang())
							   saveBcLogToBaDb(kgConvert("%1#簇温度高, 启动风机(DO%1).").arg(k+1).arg(doStg.doIndex+1));
                            else
						       saveBcLogToBaDb(kgConvert("%1# cluster temperatue high, open fan(DO%1).").arg(k+1).arg(doStg.doIndex+1));
						}
						if(m_printCount < PINTT_COUNT)
					       printf("****Temp higher, CloseBc%d DO%d (24-Fan).\n", k+1, doStg.doIndex+1);
					}
					else
					{
					    ctrlBcOpenDO(pBank, doStg);
						if(1 == fanState[k] && 0 == fanStopLogCount)
						{
							fanStopLogCount += 1;
							if(isChLang())
							   saveBcLogToBaDb(kgConvert("%1#簇温度正常, 关闭风机(DO%1).").arg(k+1).arg(doStg.doIndex+1));
							else
						       saveBcLogToBaDb(kgConvert("%1# cluster temperatue normal, close fan(DO%1).").arg(k+1).arg(doStg.doIndex+1));
						}
						fanState[k] = 0;
						if(m_printCount < PINTT_COUNT)
					       printf("****Temp not higher, OpenBc%d DO%d (24-Fan)\n", k+1, doStg.doIndex+1);
					}
					*/
				}
				if(m_printCount < PINTT_COUNT)
					 printf("****Bc%d DI1-DI6 state:%d-%d-%d-%d-%d-%d\n", 
					 k+1, pBank->usDI1, pBank->usDI2, pBank->usDI3, pBank->usDI4, pBank->usDI5,
					 pBank->usDI6);
				
				if(m_printCount < PINTT_COUNT)
					 printf("****Bc%d DO1-DO8 state:%d(Wet)-%d-%d-%d(DO4)-%d(DO5)-%d(DO6)-%d(DO7)-%d(DO8)\n", 
					 k+1, pBank->usWetState, pBank->usDry1State, pBank->usDry2State, pBank->usDry3State,
					 pBank->usDry4State,pBank->usDry5State,pBank->usDry6State,pBank->usDry7State);
			}
		}
		/*
		else if(102 == doStg.iStrategy) // 断路器脱扣
		{
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				char aEmerStop = KgGlobalData::ms_pStack->aEmerStop;
				// modified 2024-10-13
				if(g_runTickCount >= 30)// 180
				{
					bool needTuoKou = false;
				    if(fabs(g_runTickCount - 30) < 0.1)
				  	{
				  		if(0xAAAA == pBank->usBankState)
						{
				  			needTuoKou = true;
				  		}
				  	}
				    else 
				  	{
				  		if(0xAAAA != bankState[k] && 0xAAAA == pBank->usBankState)
				  		{
				  			needTuoKou = true;
				  		}
						else if(0 == bankEmg[k] && aEmerStop > 0)
						{
				  			needTuoKou = true;
				  		}
						else
							;
				  	}

					QString strLog = QString("needTuoKou1===================%1").arg((int)needTuoKou);
					writeKgLogfile(strLog);

					if(needTuoKou)
					{
					   if(bankCount[k] < PINTT_COUNT)
					   	{
					   		bankCount[k] += 1;
					   	}
					   
					   saveBcLogToBaDb(kgConvert("控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));
					   for(int k = 0; k < 2; ++k) // modified 2024-10-12
					   {
					   	   if(k > 0)
					   	   	{
					   	   		this->msleep(2000);
					   	   	}
					   	   ctrlBcCloseDO(pBank, doStg);
						   this->msleep(2000);
					   	   ctrlBcOpenDO(pBank, doStg);
					   }
					   if(bankCount[k] < PINTT_COUNT)
					      printf("****HasError, TuoKouBc%d DO%d (102-DLQ) light\n", k+1, doStg.doIndex+1);
					}
				}
				bankState[k] = pBank->usBankState;
				bankEmg[k] = aEmerStop;
			}
		}
		else if(103 == doStg.iStrategy) // 断路器脱扣 // added 2024-10-26
		{
			for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
			{
				CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
				char aEmerStop = KgGlobalData::ms_pStack->aEmerStop;
				// modified 2024-10-13
				if(g_runTickCount >= 30)
				{
					bool needTuoKou = false;
				    if(fabs(g_runTickCount - 30) < 0.1)
				  	{
				  		if(0xAAAA == pBank->usBankState)
						{
				  			needTuoKou = true;
				  		}
				  	}
				    else 
				  	{
				  		if(0xAAAA != bankStateSec[k] && 0xAAAA == pBank->usBankState)
				  		{
				  			needTuoKou = true;
				  		}
						else if(0 == bankEmgSec[k] && aEmerStop > 0)
						{
				  			needTuoKou = true;
				  		}
						else
							;
				  	}

					if(needTuoKou)
					{
					   if(bankCountSec[k] < PINTT_COUNT)
					   	{
					   		bankCountSec[k] += 1;
					   	}
					   saveBcLogToBaDb(kgConvert("控制%1#簇DO%2断路器脱扣.").arg(k+1).arg(doStg.doIndex+1));
					   for(int k = 0; k < 2; ++k) // modified 2024-10-12
					   {
					   	   if(k > 0)
					   	   	{
					   	   		this->msleep(2000);
					   	   	}
					   	   ctrlBcCloseDO(pBank, doStg);
						   this->msleep(2000);
					   	   ctrlBcOpenDO(pBank, doStg);
					   }
					   if(bankCountSec[k] < PINTT_COUNT)
					      printf("****HasError, TuoKouBc%d DO%d (103-DLQ) light\n", k+1, doStg.doIndex+1);
					}
				}
				bankStateSec[k] = pBank->usBankState;
				bankEmgSec[k] = aEmerStop;
			}
		}*/
		else if(102 == doStg.iStrategy) // 断路器脱扣 // added 2024-10-26
		{
			if(bingLianMode > 0)
			{
			    bool needTuoKou = false;
				bool hasEmgStop = false;
				bool hasFireAction = false;
				bool hasFireFault = false;
				char aEmerStop = 0;//KgGlobalData::ms_pStack->aEmerStop;
				char aFireAction = 0;// KgGlobalData::ms_pStack->aFireAction;
				char aFireFault = 0;//KgGlobalData::ms_pStack->aFireFault;
#ifdef	ND_VER_PROGRAM  // added 2021-3-13
								if (999 == pStack->usWaterBankAddr)// 电池组地址 0 - 未配置 999 - 接BA  水浸接DI4	  紧急停机
								{
									if (1 == pStack->usWaterAlarmValue) // 常开结点
									{
										aEmerStop = pStack->usDI4;
									}
									else							   // 常闭结点
									{
										aEmerStop = !pStack->usDI4;
									}
								}
#else
								aEmerStop = pStack->aEmerStop;
								aFireAction = pStack->aFireAction;
								aFireFault = pStack->aFireFault;
#endif	

				
				for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
				{
					CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
					// modified 2024-10-13
					if(g_runTickCount >= 30) // 180
					{	
					    if(fabs(g_runTickCount - 30) < 0.1)
					  	{
					  		if(isFaultTkEnabled() && 0xAAAA == pBank->usBankState)
							{
					  			needTuoKou = true;
					  		}
					  	}
					    else 
					  	{
					  		if(isFaultTkEnabled()  && 0xAAAA != bankState[k] && 0xAAAA == pBank->usBankState)
					  		{
					  			needTuoKou = true;
					  		}
							else if(0 == bankEmg[k] && aEmerStop > 0)
							{
					  			needTuoKou = true;
								hasEmgStop = true;
					  		}
							else if(0 == bankFireAction[k] && aFireAction > 0)
							{
					  			needTuoKou = true;
								hasFireAction = true;
					  		}
							else if(0 == bankFireFault[k] && aFireFault > 0)
							{
					  			needTuoKou = true;
								hasFireFault = true;
					  		}
							else 
								;
					  	}
					}
					bankState[k] = pBank->usBankState;
					bankEmg[k] = aEmerStop;
					bankFireAction[k] = aFireAction;
					bankFireFault[k] = aFireFault;
				}

				QString strLog = QString("needTuoKou1===================%1  g_runTickCount:%2")
				       .arg((int)needTuoKou).arg(g_runTickCount);
				writeKgLogfile(strLog);

				if(needTuoKou)
				{
				   // 有汇流开关时，先等汇流开关断开再脱扣BC上的断路器
				   waitConfSwitchBreaked();

				   for(int m  = 0; m < 2; ++m)
				   {
				   	  if(m > 0)
					  	 this->msleep(2000);
					  for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
				      {
				      	   if(bankCount[k] < PINTT_COUNT)
						   {
						   	   bankCount[k] += 1;
						   }
						   CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
						   ctrlBcCloseDO(pBank, doStg);
						   if(0 == m)// print one time
						   	{
						   		if(isChLang())
						   		{
							   		if(hasEmgStop)
							           saveBcLogToBaDb(kgConvert("急停,控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));
									else if(hasFireAction)
							           saveBcLogToBaDb(kgConvert("消防启动,控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));
									else if(hasFireFault)
									   saveBcLogToBaDb(kgConvert("消防故障,控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));
									else
									   saveBcLogToBaDb(kgConvert("控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));
						   	    }
								else
								{
									if(hasEmgStop)
							           saveBcLogToBaDb(kgConvert("EmergStop,control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
									else if(hasFireAction)
							           saveBcLogToBaDb(kgConvert("Fire Spray,control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
									else if(hasFireFault)
									   saveBcLogToBaDb(kgConvert("Fire Fault,control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
									else
									   saveBcLogToBaDb(kgConvert("Control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
								}
						   	}
						   if(bankCount[k] < PINTT_COUNT)
						      printf("****HasError, TuoKouBc%d DO%d (102-DLQ) light\n", k+1, doStg.doIndex+1);
					  }
					  this->msleep(2000);
					  for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
				      {
						   CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
						   ctrlBcOpenDO(pBank, doStg);
					  }
				   }
				}
				else
				{
					 for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
				      {
						   CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
						   ctrlBcOpenDO(pBank, doStg);
					  }
				}
			}
			else
			{
				for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
				{
					CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
					char aEmerStop = 0;//KgGlobalData::ms_pStack->aEmerStop;
					char aFireAction = 0;//KgGlobalData::ms_pStack->aFireAction;
					bool hasEmgStop = false;
					bool hasFireAction = false;
					#ifdef	ND_VER_PROGRAM  // added 2021-3-13
													if (999 == pStack->usWaterBankAddr)// 电池组地址 0 - 未配置 999 - 接BA  水浸接DI4	  紧急停机
													{
														if (1 == pStack->usWaterAlarmValue) // 常开结点
														{
															aEmerStop = pStack->usDI4;
														}
														else							   // 常闭结点
														{
															aEmerStop = !pStack->usDI4;
														}
													}
#else
													aEmerStop = pStack->aEmerStop;
													aFireAction = pStack->aFireAction;
#endif	

					
					// modified 2024-10-13
					if(g_runTickCount >= 30)// 180
					{
						bool needTuoKou = false;
					    if(fabs(g_runTickCount - 30) < 0.1)
					  	{
					  		if(isFaultTkEnabled() && 0xAAAA == pBank->usBankState)
							{
					  			needTuoKou = true;
					  		}
					  	}
					    else 
					  	{
					  		if(isFaultTkEnabled()  && 0xAAAA != bankState[k] && 0xAAAA == pBank->usBankState)
					  		{
					  			needTuoKou = true;
					  		}
							else if(0 == bankEmg[k] && aEmerStop > 0)
							{
					  			needTuoKou = true;
								hasEmgStop = true;
					  		}
							else if(0 == bankFireAction[k] && aFireAction > 0)
							{
					  			needTuoKou = true;
								hasFireAction = true;
					  		}
							else
								;
					  	}

						QString strLog = QString("Bank%1 needTuoKou1===================%2")
						    .arg(k+1).arg((int)needTuoKou);
						writeKgLogfile(strLog);

						if(needTuoKou)
						{
						   if(bankCount[k] < PINTT_COUNT)
						   	{
						   		bankCount[k] += 1;
						   	}
						    if(isChLang())
						   	{
							   if(hasEmgStop)
								  saveBcLogToBaDb(kgConvert("急停,控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));
							   else if(hasFireAction)
								  saveBcLogToBaDb(kgConvert("消防启动,控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));
							   else
								  saveBcLogToBaDb(kgConvert("控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));
							}
						    else
							{
								if(hasEmgStop)
						           saveBcLogToBaDb(kgConvert("EmergStop,control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
								else if(hasFireAction)
						           saveBcLogToBaDb(kgConvert("Fire Spray,control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
								else
								   saveBcLogToBaDb(kgConvert("Control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));				
							}
						   for(int k = 0; k < 2; ++k) // modified 2024-10-12
						   {
						   	   if(k > 0)
						   	   	{
						   	   		this->msleep(2000);
						   	   	}
						   	   ctrlBcCloseDO(pBank, doStg);
							   this->msleep(2000);
						   	   ctrlBcOpenDO(pBank, doStg);
						   }
						   if(bankCount[k] < PINTT_COUNT)
						      printf("****HasError, TuoKouBc%d DO%d (102-DLQ) light\n", k+1, doStg.doIndex+1);
						}
						else
						{
							ctrlBcOpenDO(pBank, doStg);
						}
					}
					bankState[k] = pBank->usBankState;
					bankEmg[k] = aEmerStop;
					bankFireAction[k] = aFireAction;
				}
			}
		}
		else if(103 == doStg.iStrategy || 109 == doStg.iStrategy || 110 == doStg.iStrategy) // 交流断路器脱扣 // added 2024-10-26
		{
			if(bingLianMode > 0)
			{
			    bool needTuoKou = false;
				bool hasEmgStop = false;
				bool hasFireAction = false;
				char aEmerStop = 0;// KgGlobalData::ms_pStack->aEmerStop;
				char aFireAction = 0;// KgGlobalData::ms_pStack->aFireAction;
#ifdef	ND_VER_PROGRAM  // added 2021-3-13
				if (999 == pStack->usWaterBankAddr)// 电池组地址 0 - 未配置 999 - 接BA  水浸接DI4	  紧急停机
				{
					
					if (1 == pStack->usWaterAlarmValue) // 常开结点
					{
						aEmerStop = pStack->usDI4;
					}
					else							   // 常闭结点
					{
						aEmerStop = !pStack->usDI4;
					}
				}
#else
				aEmerStop = pStack->aEmerStop;
				aFireAction = pStack->aFireAction;
#endif	

				
				for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
				{
					CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
					// modified 2024-10-13
					if(g_runTickCount >= 40)
					{	
					    if(fabs(g_runTickCount - 40) < 0.1)
					  	{
					  		/*if(isFaultTkEnabled() && 0xAAAA == pBank->usBankState)
							{
					  			needTuoKou = true;
					  		}*/
					  	}
					    else 
					  	{
					  		/*if(isFaultTkEnabled() && 0xAAAA != bankStateSec[k] && 0xAAAA == pBank->usBankState)
					  		{
					  			needTuoKou = true;
					  		}
							else */
							if(isEmgTkEnabled() && 0 == bankEmgSec[k] && aEmerStop > 0)
							{
					  			needTuoKou = true;
								hasEmgStop = true;
					  		}
							else if(0 == bankFireActionSec[k] && aFireAction > 0)
							{
					  			needTuoKou = true;
								hasFireAction = true;
					  		}
							else
								;
					  	}
					}
					bankStateSec[k] = pBank->usBankState;
					bankEmgSec[k] = aEmerStop;
					bankFireActionSec[k] = aFireAction;
				}

				QString strLog = QString("needTuoKou2===================%1  g_runTickCount:%2")
				       .arg((int)needTuoKou).arg(g_runTickCount);
				writeKgLogfile(strLog);

				if(needTuoKou)
				{
				   // 有汇流开关时，先等汇流开关断开再脱扣BC上的断路器
				   waitConfSwitchBreaked();
				 
				   for(int m  = 0; m < 2; ++m)
				   {
				   	  if(m > 0)
					  	 this->msleep(2000);
					  for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
				      {
				      	   if(bankCountSec[k] < PINTT_COUNT)
						   {
						   	   bankCountSec[k] += 1;
						   }
						   CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
						   ctrlBcCloseDO(pBank, doStg);
						   if(0 == m)// print one time
						   	{
						   		if(isChLang())
						   		{
							   		if(hasEmgStop)
							           saveBcLogToBaDb(kgConvert("急停,控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));
									else if(hasFireAction)
									   saveBcLogToBaDb(kgConvert("消防启动,控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));					
									else
									   saveBcLogToBaDb(kgConvert("控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));
						   		}
								else
								{
									if(hasEmgStop)
							           saveBcLogToBaDb(kgConvert("EmergStop,control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
									else if(hasFireAction)
							           saveBcLogToBaDb(kgConvert("Fire Spray,control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
									//else if(hasFireFault)
									//   saveBcLogToBaDb(kgConvert("Fire Fault,control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
									else
									   saveBcLogToBaDb(kgConvert("Control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
								}
							}
						   if(bankCountSec[k] < PINTT_COUNT)
						      printf("****HasError, TuoKouBc%d DO%d (103-DLQ) light\n", k+1, doStg.doIndex+1);
					  }
					  this->msleep(2000);
					  for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
				      {
						   CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
						   ctrlBcOpenDO(pBank, doStg);
					  }
				   }
				}
				else
				{
					 for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
				      {
						   CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
						   ctrlBcOpenDO(pBank, doStg);
					  }
				}
				
			}
			else
			{
				for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
				{
					CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);
					bool hasEmgStop = false;
					bool hasFireAction = false;
					char aEmerStop = 0;// KgGlobalData::ms_pStack->aEmerStop;
					char aFireAction = 0;// KgGlobalData::ms_pStack->aFireAction;
#ifdef	ND_VER_PROGRAM  // added 2021-3-13
					if (999 == pStack->usWaterBankAddr)// 电池组地址 0 - 未配置 999 - 接BA  水浸接DI4     紧急停机
					{
						if (1 == pStack->usWaterAlarmValue) // 常开结点
						{
							aEmerStop = pStack->usDI4;
						}
						else                               // 常闭结点
						{
							aEmerStop = !pStack->usDI4;
						}
					}
#else
					aEmerStop = pStack->aEmerStop;
					aFireAction = pStack->aFireAction;
#endif		
					
					// modified 2024-10-13
					if(g_runTickCount >= 40)// 180
					{
						bool needTuoKou = false;
					    if(fabs(g_runTickCount - 40) < 0.1)
					  	{
					  		/*if(isFaultTkEnabled() && 0xAAAA == pBank->usBankState)
							{
					  			needTuoKou = true;
					  		}*/
					  	}
					    else 
					  	{
					  		/*if(isFaultTkEnabled() && 0xAAAA != bankStateSec[k] && 0xAAAA == pBank->usBankState)
					  		{
					  			needTuoKou = true;
					  		}
							else */
							if(isEmgTkEnabled() && 0 == bankEmgSec[k] && aEmerStop > 0)
							{
					  			needTuoKou = true;
								hasEmgStop = true;
					  		}
							else if(0 == bankFireActionSec[k] && aFireAction > 0)
							{
					  			needTuoKou = true;
								hasFireAction = true;
					  		}
							else
								;
					  	}

						QString strLog = QString("Bank%1 needTuoKou2===================%2")
						    .arg(k+1).arg((int)needTuoKou);
						writeKgLogfile(strLog);

						if(needTuoKou)
						{
						   if(bankCountSec[k] < PINTT_COUNT)
						   	{
						   		bankCountSec[k] += 1;
						   	}

							if(isChLang())
							{
							    if(hasEmgStop)
							       saveBcLogToBaDb(kgConvert("急停,控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));
								else if(hasFireAction)
								   saveBcLogToBaDb(kgConvert("消防启动,控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));										
								else
								   saveBcLogToBaDb(kgConvert("控制%1#簇脱扣断路器(DO%2).").arg(k+1).arg(doStg.doIndex+1));
							}
							else
							{
								if(hasEmgStop)
						           saveBcLogToBaDb(kgConvert("EmergStop,control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
								else if(hasFireAction)
						           saveBcLogToBaDb(kgConvert("Fire Spray,control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
								//else if(hasFireFault)
								//   saveBcLogToBaDb(kgConvert("Fire Fault,control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
								else
								   saveBcLogToBaDb(kgConvert("Control %1# cluster trip switch(DO%2).").arg(k+1).arg(doStg.doIndex+1));
							}
							
						   for(int k = 0; k < 2; ++k) // modified 2024-10-12
						   {
						   	   if(k > 0)
						   	   	{
						   	   		this->msleep(2000);
						   	   	}
						   	   ctrlBcCloseDO(pBank, doStg);
							   this->msleep(2000);
						   	   ctrlBcOpenDO(pBank, doStg);
						   }
						   if(bankCountSec[k] < PINTT_COUNT)
						      printf("****HasError, TuoKouBc%d DO%d (103-DLQ) light\n", k+1, doStg.doIndex+1);
						}
						else
						{
							ctrlBcOpenDO(pBank, doStg);
						}
					}
					bankStateSec[k] = pBank->usBankState;
					bankEmgSec[k] = aEmerStop;
					bankFireActionSec[k] = aFireAction;
				}
			}
		}
		else
		{
			;
		}
    }
}


BcDiDoThread::BcDiDoThread(QObject *parent)
	: QThread(parent)
{
	printf("BcDiDoThread init begin\n");
	for(int i = 0; i < 30; ++i)
	{
		for(int k = 0; k < 50; ++k)
		{
			m_bcDiOldState[i][k] = 99;
		}
	}

	for(int i = 0; i < 30; ++i)
	{
		for(int k = 0; k < 10; ++k)
		{
			m_bcResDiOldState[i][k] = 99;
		}

		m_oldCtrlFanState[i] = 0;
	    m_closeFanReqCount[i] = 0;
	 // m_closeReqStartTime[i];
	}
	printf("BcDiDoThread init over\n");

	m_printCount = 0;
	m_bcDoLogCount = 0;
	m_runCount = 0;
}
	
BcDiDoThread::~BcDiDoThread()
{

}

void BcDiDoThread::run()
{
	sleep(1);//程序刚启动时，本程序晚一点运行 
	sleep(2);
	
	CBattStack *pStack = KgGlobalData::ms_pRTDB->getStack(0);
	CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(0);
	
	while(1)
	{
	   	//msleep(150);
	   	msleep(250);
		
		if(g_runTickCount < 1800)
		{
			//g_runTickCount += 0.15;
			g_runTickCount += 0.25;
		}
		
	    dealwithBCDIState(pStack);
		dealwithBCDOState();
		
		if(m_printCount < PINTT_COUNT)
		{
		   m_printCount += 1;
		}

		if(m_bcDoLogCount < 3000)
		{
		   m_bcDoLogCount += 1;
		}

		if(++m_runCount > 10000)
		{
			m_runCount = 0;
		}
	}
}

